# 指定文件编码为UTF-8
# coding: utf-8

# 导入系统模块和操作系统模块
import sys, os

# 将父目录添加到系统路径，以便导入父目录中的模块
sys.path.append(os.pardir)

# 导入NumPy数值计算库
import numpy as np

# 导入pickle模块，用于序列化和反序列化Python对象
import pickle

# 从dataset.mnist模块导入load_mnist函数
from dataset.mnist import load_mnist

# 从common.functions模块导入sigmoid和softmax激活函数
from common.functions import sigmoid, softmax

# 定义获取MNIST数据的函数
def get_data():
    # 加载MNIST数据集
    # normalize=True: 对图像数据进行归一化
    # flatten=True: 将图像展平为一维数组
    # one_hot_label=False: 不使用one-hot编码的标签
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    # 返回测试集数据和标签
    return x_test, t_test

# 定义初始化神经网络的函数
def init_network():
    # 以二进制读取模式打开预训练权重文件
    with open("sample_weight.pkl", 'rb') as f:
        # 使用pickle加载网络参数
        network = pickle.load(f)
    # 返回加载的网络参数
    return network

# 定义预测函数（批量处理）
def predict(network, x):
    # 从网络参数中提取各层权重
    w1, w2, w3 = network['W1'], network['W2'], network['W3']
    # 从网络参数中提取各层偏置
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    # 第一层前向传播（矩阵乘法）
    a1 = np.dot(x, w1) + b1
    # 第一层激活函数
    z1 = sigmoid(a1)
    # 第二层前向传播
    a2 = np.dot(z1, w2) + b2
    # 第二层激活函数
    z2 = sigmoid(a2)
    # 第三层前向传播
    a3 = np.dot(z2, w3) + b3
    # 输出层使用softmax激活函数
    y = softmax(a3)

    # 返回预测结果
    return y

# 主程序开始
# 获取测试数据和标签
x, t = get_data()
# 初始化神经网络
network = init_network()

# 设置批处理大小
batch_size = 100
# 初始化正确分类计数器
accuracy_cnt = 0

# 使用批处理方式遍历测试集
for i in range(0, len(x), batch_size):
    # 获取当前批次的数据
    x_batch = x[i:i+batch_size]
    # 对当前批次进行预测
    y_batch = predict(network, x_batch)
    # 获取预测结果中概率最高的类别索引（按行取最大值）
    p = np.argmax(y_batch, axis=1)
    # 统计当前批次中预测正确的数量并累加
    accuracy_cnt += np.sum(p == t[i:i+batch_size])

# 计算并打印准确率（正确预测数/总样本数）
print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
